#include<bits/stdc++.h>
#define ll long long
template <typename T> inline void read(T &x) {
    x = 0; char ch = getchar(); int f = 1;
    while (!isdigit(ch) && ch ^ '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar(); x *= f;
}
using namespace std;
const int N=1005,mo=147744151;
int q,n,m,P,pre[N][N],A[N][N],sum[4*N+1][N],ans;
struct Tree
{
	int l,r,sum;
};
struct Tree2
{
	int l,r;
	Tree t[4*N+1];
}t[4*N+1];
void update2(int p)
{
	for(int a=1;a<=m;a++)
	{
		sum[p][a]=(ll)sum[p*2][a]*sum[p*2+1][a]%P;
	}
}
void update(int k,int p)
{
	t[k].t[p].sum=(ll)t[k].t[p*2].sum*t[k].t[p*2+1].sum%P;
}
void maketree(int k,int p,int l,int r)
{
	t[k].t[p].l=l,t[k].t[p].r=r;
	if(l==r)
	{
		t[k].t[p].sum=sum[k][l];
		return;
	}
	int mid=(l+r)/2;
	maketree(k,p*2,l,mid);
	maketree(k,p*2+1,mid+1,r);
	update(k,p);
}
void maketree2(int p,int l,int r)
{
	t[p].l=l,t[p].r=r;
	if(l==r)
	{
		for(int a=1;a<=m;a++) sum[p][a]=A[l][a];
		maketree(p,1,1,m);
		return;
	}
	int mid=(l+r)/2;
	maketree2(p*2,l,mid);
	maketree2(p*2+1,mid+1,r);
	update2(p); 
	maketree(p,1,1,m);
}
int get_sum(int k,int p,int l,int r)
{
	if(t[k].t[p].l>=l&&t[k].t[p].r<=r) return t[k].t[p].sum;
	int mid=(t[k].t[p].l+t[k].t[p].r)/2,tot=1;
	if(l<=mid) tot=(ll)tot*get_sum(k,p*2,l,r)%P;
	if(r>mid) tot=(ll)tot*get_sum(k,p*2+1,l,r)%P;
	return tot;
}
int get_sum2(int p,int l1,int r1,int l2,int r2)
{
	if(t[p].l>=l1&&t[p].r<=r1)
	{
		return get_sum(p,1,l2,r2);
	}
	int mid=(t[p].l+t[p].r)/2,tot=1;
	if(l1<=mid) tot=(ll)tot*get_sum2(p*2,l1,r1,l2,r2)%P;
	if(r1>mid) tot=(ll)tot*get_sum2(p*2+1,l1,r1,l2,r2)%P;
	return tot;
}
int main()
{
	freopen("tsuki.in","r",stdin);
	freopen("tsuki.out","w",stdout);
    read(n),read(m),read(P);
    for(int a=1;a<=n;a++)
    {
    	for(int b=1;b<=m;b++)
    	{
    		read(A[a][b]);
		}
	}
	maketree2(1,1,n);
	read(q);
	for(int i=1;i<=q;i++) 
	{
		int x,y,xx,yy;
		read(x),read(y),read(xx),read(yy);
		ans=(ans+(i^(get_sum2(1,x,xx,y,yy))))%mo;
	}
	printf("%d",ans);
}
